#include "cmdlogin.h"
#include "../mainctrl.h"
#include "../cmd/dataprepare.h"
#include "../cmd/cmdselectdatafromdbsvr.h"
#include "MsgComm.pb.h"
#include "MsgTips.pb.h"

CT_REGISTER_ASYNCCMD(ID_MAIN_LOGIN, CCmdLogin);

int CCmdLogin::Do(void* pData)
{
    CT_ASSERT(pData);

    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_LOGIN || pstParam->m_pstMsgHead->msgtype() != EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d", ID_MAIN_LOGIN, pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    if (pstMainCtrl->GetOnlineUserNum() >= MAX_PLAYER_ONLINE)
    {
        return AnsClients(ERROR_ONLINE_FULL);
    }

    if (!stReq.has_user_token())
    {
        CT_ERROR(("CCmdLogin User Login But UserToken Not Set"));
        return AnsClients(RET_REQ_NOT_COMPLETE);
    }

    if (!stReq.has_platform())
    {
        CT_ERROR(("CCmdLogin User Login But Platform Flag Not Set"));
        return AnsClients(RET_REQ_NOT_COMPLETE);
    }

    szUserToken.Set("%s", stReq.user_token().c_str());
    if (szUserToken.GetDataLen() <= 0)
    {
        CT_ERROR(("CCmdLogin User Login But UserToken Length Zero"));
        return AnsClients(RET_REQ_NOT_COMPLETE);
    }

    if (szUserToken.GetDataLen() >= USER_TOKEN_LEN)
    {
        CT_ERROR(("CCmdLogin UserToken %s Len %d Too Long", szUserToken(), szUserToken.GetDataLen()));
        return AnsClients(ERROR_USER_TOKEN_LEN);
    }

    CTSizeString<MAX_PLATFORM_STR_LEN> szPlatform;
    szPlatform.Set("%s", stReq.platform().c_str());
    if (szPlatform.GetDataLen() <= 0)
    {
        CT_ERROR(("CCmdLogin User Login But Platform Flag Length Zero"));
        return AnsClients(RET_REQ_NOT_COMPLETE);
    }

    int iPlatfrom = pstMainCtrl->GetPlatform(szPlatform.Get());
    if (PLATFORM_MACRO_UNKNOWN == iPlatfrom)
    {
        return ERROR_SYS_PLATFORM_FLAG;
    }

    //版署账号检查
    if (PLATFORM_MACRO_BANSHU == iPlatfrom)
    {
        if (!stReq.has_password())
        {
            CT_ERROR(("CCmdLogin User Login But PassWord Not Set"));
            return AnsClients(RET_REQ_NOT_COMPLETE);
        }

        CTSizeString<USER_PASSWORD_LEN> szPassWord;
        szPassWord.Set("%s", stReq.password().c_str());
        iRet = pstMainCtrl->CheckAccount(szUserToken, szPassWord);
        if (iRet != RET_OK)
        {
            return AnsClients(RET_SYS_PB_ILLEGAL_USER);
        }
    }

    bHasCheckDBSvr = false;
    u64GID = 0;

    int iIndex = pstMainCtrl->m_stUserTokenHash.HashFind(szUserToken);

    if (iIndex >= 0)
    {
        bHasCheckDBSvr = true;
        u64GID = pstMainCtrl->m_stUserTokenHash[iIndex];
    }

    return LogicDo(RET_OK);
}

int CCmdLogin::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        CT_ERROR(("CCmdLogin LogicDo Error %d", iRet));
        return AnsClients(iRet);
    }

    if (!bHasCheckDBSvr)
    {
        CCmdSelectDataFromDBSvr* pstCmd = (CCmdSelectDataFromDBSvr*)CT_CMDFACTORY->CreateCmd(ID_MAINDB_SELECTDATA);
        if (!pstCmd)
        {
            CT_ERROR(("Create Cmd %d Pointer Null", ID_MAINDB_SELECTDATA));
            return AnsClients(RET_SYSTEM_FAIL);
        }

        bHasCheckDBSvr = true;

        pstCmd->pstMainCtrl = pstMainCtrl;
        pstCmd->stReq.m_ucCheckUpdateMgr = 0;
        pstCmd->stReq.m_stKey.m_chDataType = DT_USERTOKEN_TO_GID;
        pstCmd->stReq.m_stKey.m_u64ID = 0;
        pstCmd->stReq.m_stKey.m_sStrID.Set("%s", szUserToken());

        RegisterChild(pstCmd);

        return pstCmd->Do(NULL);
    }

    PREPARE_PLAYER_DB_INFO(this, u64GID);
    ASSERT_DB_INFO_PREPARED(u64GID);

    int iIndex = pstMainCtrl->m_stPlayerDBInfoHash.HashFind(u64GID);
    if (iIndex < 0)
    {
        CT_ERROR(("CCmdLogin UserToken %s LoginDo GID %llu Not In DBInfo Hash", szUserToken(), u64GID));
        return AnsClients(RET_NO_USER);
    }

    CPlayerDBInfo& stPlayerDBInfo = pstMainCtrl->m_stPlayerDBInfoHash[iIndex];

    CPlatformInfo stPlatformInfo; //平台信息暂时用假数据 byronwei

    //设置登录 踢掉已有的用户
    bool bDualLogin = false;
    iIndex = pstMainCtrl->m_stUserOnlineDataHash.HashFind(u64GID);
    if (iIndex >= 0 && !pstMainCtrl->m_stUserOnlineDataHash[iIndex].IsUserOffline())
    {
        CUserOnlineData& stUserOnlineData = pstMainCtrl->m_stUserOnlineDataHash[iIndex];
        CEnpNetHead stOldHandle;
        stUserOnlineData.GetEnpHeadInfo(stOldHandle);
        if (stOldHandle.uiHandle == stEnpHead.uiHandle)
        {
			stUserOnlineData.SetLoginTime(pstMainCtrl->m_iNow);
            CT_ERROR(("CCmdLogin UserToken %s GID %llu Repeate Login", szUserToken(), u64GID));
            bDualLogin = true;
        }
        else
        {
            if (stOldHandle.uiHandle > 0)
            {
                MsgAnsTips stTips;
                CMainCtrl::m_pstMain->m_szSizeString.Set("%llu", u64GID);
                stTips.set_gid(CMainCtrl::m_pstMain->m_szSizeString());
                stTips.set_opt(ENUM_SEND_TIP_REPEATED_LOGIN);
                pstMainCtrl->SendMessageToClient(stOldHandle, ID_MAIN_TIPS, stTips, false);
            }

            iRet = pstMainCtrl->SetOffline(u64GID, stOldHandle);
            if (iRet != RET_OK)
            {
                CT_ERROR(("UserToken %s GID %llu Repeate Login SetOffline Error %d", szUserToken(), u64GID, iRet));
                return AnsClients(RET_SYSTEM_FAIL);
            }


            iRet = pstMainCtrl->SetOnline(u64GID, stEnpHead, stPlatformInfo);
            if (iRet != RET_OK)
            {
                CT_ERROR(("CCmdLogin UserToken %s GID %llu SetOnline Error %d", szUserToken(), u64GID, iRet));
                return AnsClients(RET_SYSTEM_FAIL);
            }
        }
    }
    else
    {
        iRet = pstMainCtrl->SetOnline(u64GID, stEnpHead, stPlatformInfo);
        if (iRet != RET_OK)
        {
            CT_ERROR(("CCmdLogin UserToken %s GID %llu SetOnline Error %d", szUserToken(), u64GID, iRet));
            return AnsClients(RET_SYSTEM_FAIL);
        }
        if(!CTTimeUtils::IsSameDay(pstMainCtrl->m_iNow, stPlayerDBInfo._stPlayerBaseInfo._iLastOfflineTime, 0))
        {
            pstMainCtrl->m_stOssMgr.TriggerAct(stPlayerDBInfo._stPlayerBaseInfo);
            pstMainCtrl->m_stOssMgr.TriggerCardslog(stPlayerDBInfo._stPlayerDetailInfo);
        }
    }

    iIndex = pstMainCtrl->m_stUserOnlineDataHash.HashFind(u64GID);
    if (iIndex < 0)
    {
        CT_ERROR(("CCmdLogin UserToken %s LoginDo GID %llu Not In Online Hash", szUserToken(), u64GID));
        return AnsClients(RET_NO_USER);
    }

    CUserOnlineData& stUserOnlineData = pstMainCtrl->m_stUserOnlineDataHash[iIndex];

    //防沉迷
    pstMainCtrl->UpdateDefendOffline(stPlayerDBInfo, stUserOnlineData);

	//初始化任务
    pstMainCtrl->m_stDailyTaskMgr.InitDailyTask(stPlayerDBInfo);

    pstMainCtrl->m_stQualifyingMgr.CheckQualifySeason(stPlayerDBInfo);

    pstMainCtrl->m_stGrowthFundMgr.InitGrowthFund(stPlayerDBInfo);

	//登陆后主动推送信息给玩家
	NotifyInfoToUser(stPlayerDBInfo, stUserOnlineData);

    return AnsClients(RET_OK);
}

int CCmdLogin::CallBack(int iRet)
{
    if (!m_pstChild)
    {
        CT_ERROR(("CCmdLogin UserToken %s CallBack Child Pointer Null", szUserToken()));
        return AnsClients(RET_SYSTEM_FAIL);
    }

    CCmdSelectDataFromDBSvr* pstCmd = (CCmdSelectDataFromDBSvr*)m_pstChild;

    if (pstCmd->stAns.stResult.iResultID == RET_OK)
    {
        iRet = pstMainCtrl->DataDecode(u64GID, pstCmd->stAns.pszData, pstCmd->stAns.iDataLen);
        if (iRet != RET_OK || u64GID <= 0)
        {
            CT_ERROR(("CCmdLogin UserToken %s CallBack Decode %d or GID %llu Error", szUserToken(), iRet, u64GID));
            return AnsClients(RET_SYSTEM_FAIL);
        }

        return LogicDo(RET_OK);
    }
    else
    {
        CT_ERROR(("CCmdLogin UserToken %s CallBack GID %llu Child ResultID %d", szUserToken(), u64GID,
            pstCmd->stAns.stResult.iResultID));
        return AnsClients(pstCmd->stAns.stResult.iResultID);
    }

    return LogicDo(iRet);
}

int CCmdLogin::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    if (RET_OK != iRet)
    {
        CT_ERROR(("CCmdLogin UserToken %s error %d", szUserToken(), iRet));
    }

    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    int iIndex = pstMainCtrl->m_stPlayerDBInfoHash.HashFind(u64GID);
    if (iIndex < 0)
    {
        CT_ERROR(("CCmdLogin UserToken %s LoginDo GID %llu Not In DBInfo Hash", szUserToken(), u64GID));
        return Done(iRet);
    }
    CPlayerDBInfo& stPlayerDBInfo = pstMainCtrl->m_stPlayerDBInfoHash[iIndex];
    
    MsgRoleInfo* pstMsgRoleInfo = stAns.mutable_role_info();
    if (pstMsgRoleInfo)
    {
        CMainCtrl::m_pstMain->m_stRoleMgr.CopyToMsgRoleInfo(stPlayerDBInfo, *pstMsgRoleInfo);
    }
    else
    {
        CT_ERROR(("GID(%llu) MsgRoleInfo Pointer Null!", u64GID));
    }

    MsgQualifyInfo* pstMsgQualify = stAns.mutable_qualify();
    if (pstMsgQualify)
    {
        CMainCtrl::m_pstMain->m_stRoleMgr.CopyToMsgQualify(stPlayerDBInfo, *pstMsgQualify);
    }
    else
    {
        CT_ERROR(("GID(%llu) MsgQualifyInfo Pointer Null!", u64GID));
    }

    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_ERROR(("CCmdLogin UserToken %s AnswerToClient Error", szUserToken()));
        return Done(RET_SYS_ERROR);
    }
    
    return Done(iRet);
}

void CCmdLogin::NotifyInfoToUser(CPlayerDBInfo& stPlayerDBInfo, CUserOnlineData& stUserOnlineData)
{
	pstMainCtrl->m_stCardMgr.NotifyRoleCard(stPlayerDBInfo);

	pstMainCtrl->m_stDeckMgr.NotifyRoleDeck(stPlayerDBInfo);

	pstMainCtrl->m_stMailSystemMgr.GetSystemMail(stPlayerDBInfo);
}

